package weeny.recycle;

import java.awt.event.MouseEvent;
import java.awt.geom.Point2D;
import javax.swing.SwingUtilities;

import prefuse.Display;
import prefuse.Visualization;
import prefuse.controls.DragControl;
import prefuse.visual.EdgeItem;
import prefuse.visual.VisualItem;
import weeny.pre.util.Geom;

@Deprecated
public class DragAlongEdgeController extends DragControl {
	public static class AfterHandler{
		public void afterItemPressed(VisualItem item){}
		public void afterItemRelease(VisualItem item){}
		public void afterItemDragged(VisualItem item){}
	}
	
	private Point2D source = new Point2D.Double();
	private Point2D target = new Point2D.Double();
	private AfterHandler handler = null;
	private String edgeField = null;
	private Visualization m_vis;
	private String group;
	private boolean canDrag(VisualItem item){
		return m_vis.getFocusGroup(group)!=null && m_vis.getFocusGroup(group).containsTuple(item);
	}
	public DragAlongEdgeController(Visualization vis, String groupName, String edgeField, AfterHandler handler) {
		this(vis, groupName, edgeField);
		this.handler = handler;
	}
	public DragAlongEdgeController(Visualization vis, String groupName, String edgeField){
		super(true);
		this.group = groupName;
		this.m_vis = vis;
		this.edgeField = edgeField;
		this.handler = null;
	}
	@Override
	public void itemEntered(VisualItem item, MouseEvent e) {
		if (canDrag(item)) {
			super.itemEntered(item, e);
		}
	}
	@Override
	public void itemExited(VisualItem item, MouseEvent e) {
		if (canDrag(item)) {
			super.itemExited(item, e);
		}
	}
	@Override
	public void itemPressed(VisualItem item, MouseEvent e) {
		if (canDrag(item)) {
			super.itemPressed(item, e);
			if (handler != null) {
				handler.afterItemPressed(item);
			}
		}
	}
	@Override
	public void itemReleased(VisualItem item, MouseEvent e) {
		if (canDrag(item)) {
			super.itemReleased(item, e);
			if (handler != null) {
				handler.afterItemRelease(item);
			}
		}
	}
	@Override
	public void itemDragged(VisualItem item, MouseEvent e) {
		if (canDrag(item)){
			if (!SwingUtilities.isLeftMouseButton(e)) return;
			EdgeItem edge = (EdgeItem) item.get(edgeField);
			dragged = true;
			Display d = (Display)e.getComponent();
			d.getAbsoluteCoordinate(e.getPoint(), temp);
			double dx = temp.getX()-down.getX();
			double dy = temp.getY()-down.getY();
			double x = item.getX();
			double y = item.getY();	
			if(Math.abs(Geom.deltaX(edge))>Math.abs(Geom.deltaY(edge))){
				//width is bigger than height
				if (Geom.deltaX(edge)>0) {
					Geom.dumpPnt(edge.getSourceItem(), source);
					Geom.dumpPnt(edge.getTargetItem(), target);
				}
				else{
					Geom.dumpPnt(edge.getSourceItem(), target);
					Geom.dumpPnt(edge.getTargetItem(), source);
				}
				if (x+dx >= target.getX()) {
					item.setStartX(x);           item.setStartY(y);
					item.setX(target.getX());    item.setY(target.getY());
					item.setEndX(target.getX()); item.setEndY(target.getY());
					down.setLocation(target.getX(), temp.getY());
				}
				else if (x+dx <= source.getX()) {
					item.setStartX(x);           item.setStartY(y);
					item.setX(source.getX());    item.setY(source.getY());
					item.setEndX(source.getX()); item.setEndY(source.getY());
					down.setLocation(source.getX(), temp.getY());
				}
				else{
					double yy = source.getY()+(x+dx-source.getX())/(target.getX()-source.getX())*(target.getY()-source.getY());
					item.setStartX(x);  item.setStartY(y);
					item.setX(x+dx);    item.setY(yy);
					item.setEndX(x+dx); item.setEndY(yy);
					down.setLocation(temp);
				}
			}
			else{
				if (edge.getSourceItem().getY() < edge.getTargetItem().getY()) {
					source.setLocation(edge.getSourceItem().getX(), edge.getSourceItem().getY());
					target.setLocation(edge.getTargetItem().getX(), edge.getTargetItem().getY());
				}
				else{
					target.setLocation(edge.getSourceItem().getX(), edge.getSourceItem().getY());
					source.setLocation(edge.getTargetItem().getX(), edge.getTargetItem().getY());
				}
				if (y+dy >= target.getY()) {
					item.setStartX(x);           item.setStartY(y);
					item.setX(target.getX());    item.setY(target.getY());
					item.setEndX(target.getX()); item.setEndY(target.getY());
					down.setLocation(temp.getX(), target.getY());
				}
				else if (y+dy <= source.getY()) {
					item.setStartX(x);           item.setStartY(y);
					item.setX(source.getX());    item.setY(source.getY());
					item.setEndX(source.getX()); item.setEndY(source.getY());
					down.setLocation(temp.getX(), source.getY());
				}
				else{
					double xx = source.getX()+(y+dy-source.getY())/(target.getY()-source.getY())*(target.getX()-source.getX());
					item.setStartX(x);  item.setStartY(y);
					item.setX(xx);    item.setY(y+dy);
					item.setEndX(xx); item.setEndY(y+dy);
					down.setLocation(temp);
				}
			}
			if (handler != null) {
				handler.afterItemDragged(item);
			}
			if ( repaint )
				item.getVisualization().repaint();			        
		}
		else if (canDrag(item)) {
			super.itemDragged(item, e);
		}
	}
}
